#include <sched.h>
#include <stdio.h>
#include <stdlib.h>

#include "hw2_syscalls.h"

int fibonaci(int n)
{
    if (n < 2)
        return n;
    return fibonaci(n-1) + fibonaci(n-2);
}


const char * reason_to_str(enum sched_reason reason)
{
	switch (reason) {
	case SWITCH_REASON_CREATE:
		return "SWITCH_REASON_CREATE";
	case SWITCH_REASON_END:
		return "SWITCH_REASON_END";
	case SWITCH_REASON_YIELD:
		return "SWITCH_REASON_YIELD";
	case SWITCH_REASON_MQ_OVERDUE:
		return "SWITCH_REASON_MQ_OVERDUE";
	case SWITCH_REASON_TO_WAIT:
		return "SWITCH_REASON_TO_WAIT";
	case SWITCH_REASON_FROM_WAIT:
		return "SWITCH_REASON_FROM_WAIT";
	case SWITCH_REASON_TIMESLICE_END:
		return "SWITCH_REASON_TIMESLICE_END";
	case SWITCH_REASON_INVALID:
		return "SWITCH_REASON_INVALID";
	default:
		return "SWITCH_REASON_???";
	}
}

const char* policy_to_str(int policy)
{
    switch (policy) {
    case 0:
        return "OTHER";
    case 1:
        return "FIFO";
    case 2:
        return "RR";
    case 4:
        return "MQ";
    }
    
    return "????";
}

void print_stats()
{
	struct switch_info info[150];
	int i, ret;

	if (-1 == (ret = get_scheduling_statistic(info))) {
		perror("Can't get stats");
		exit(1);
	}
    printf("[U] printing %d stats:\n", ret);
	for (i = 0; i < ret; ++i) {
		printf("%10lu: [%5d|%11s]->[%5d|%11s] = %s\n",
		       info[i].time,
		       info[i].previous_pid,
		       policy_to_str(info[i].previous_policy),
		       info[i].next_pid,
		       policy_to_str(info[i].next_policy),
		       reason_to_str(info[i].reason));
	}
}

int main(int argc, char** argv)
{
    struct sched_param sp;

    printf("[U] Current policy: %s\n", policy_to_str(sched_getscheduler(getpid())));
    print_stats();
    
    sp.trial_num = 5;    
    sp.sched_priority = 0;    
    sched_setscheduler(getpid(), SCHED_MQ, &sp);
    
    printf("[U] Current policy: %s\n", policy_to_str(sched_getscheduler(getpid())));
    print_stats();
    
    printf("[U] running fibonaci\n");
    fibonaci(40);
    print_stats();
    
    return 0;
}
